package com.deruan.hotcore.resource.gui.tree;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.swing.JPopupMenu;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.columba.api.gui.frame.IFrameMediator;
import org.columba.core.gui.context.ContextResultBox;
import org.columba.core.gui.menu.ExtendablePopupMenu;
import org.columba.core.gui.menu.MenuXMLDecoder;
import org.columba.core.gui.search.api.IResultPanel;
import org.columba.core.io.DiskIO;
import org.columba.core.search.api.IResultEvent;
import org.columba.core.search.api.ISearchResult;
import org.columba.mail.folder.IMailFolder;
import org.columba.mail.folder.virtual.VirtualFolder;
import org.columba.mail.gui.frame.SocialNetViewOwner;
import org.columba.mail.gui.socialnet.ISocialNetController;
import org.columba.mail.gui.tree.FolderSelectionEvent;
import org.columba.mail.gui.tree.IFolderSelectionEvent;
import org.columba.mail.gui.tree.IFolderSelectionListener;
import org.columba.mail.gui.tree.ITreeController.SORTING_MODE_ENUM;
import org.columba.mail.gui.tree.comparator.FolderComparator;
import org.columba.mail.gui.tree.comparator.UnreadFolderComparator;

import edu.uci.ics.jung.graph.Vertex;

public class SearchResultTreeController implements TreeSelectionListener,
TreeWillExpandListener, IResultTreeController, IResultPanel
{
	private IMailFolder selectedFolder;

	private SearchTreeView view;

	private IFrameMediator frameController;

	private ExtendablePopupMenu menu;

	private FolderComparator folderComparator;

	protected EventListenerList listenerList = new EventListenerList();

	private Map<String, ContextResultBox> contextMap = new Hashtable<String, ContextResultBox>();
	
	private String providerTechnicalName;

	private String criteriaTechnicalName;
	/**
	 * Constructor for tree controller.
	 *
	 * @param controller
	 *            the parent controller.
	 * @param model
	 *            the tree model to display.
	 */
	public SearchResultTreeController(IFrameMediator controller) {
		
		frameController = controller;
		
		view = new SearchTreeView(new ResultTreeModel());
		//view.setSortingEnabled(false);

		view.addTreeWillExpandListener(this);

		ResultTreeCellRenderer renderer = new ResultTreeCellRenderer();
		view.setCellRenderer(renderer);

		//getView().setTransferHandler(new TreeViewTransferHandler(controller));
		getView().setDragEnabled(true);

		getView().getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

		getView().addTreeSelectionListener(this);
	}

	/**
	 * @see org.columba.mail.gui.tree.ITreeController#sortAscending(boolean)
	 */
	public void sortAscending(boolean ascending) {
		folderComparator.setAscending(ascending);
		//view.setSortingComparator(folderComparator);
	}

	/**
	 * Returns the tree view.
	 *
	 * @return the tree view.
	 */
	public SearchTreeView getView() {
		return view;
	}

	/**
	 * Set the specified folder as seleceted.
	 *
	 * @param folder
	 *            the new selected folder.
	 */
	public void setSelected(IMailFolder folder) {
		view.clearSelection();

		TreePath path = folder.getSelectionTreePath();

		// @author: fdietz never request focus
		//view.requestFocus();
		/*
		 * view.setLeadSelectionPath(path); view.setAnchorSelectionPath(path);
		 */
		view.setSelectionPath(path);
		view.expandPath(path);

		this.selectedFolder = folder;

	}

	/**
	 * Creates a Popup menu.
	 */
	public void createPopupMenu() {
		try {
			InputStream is = DiskIO
					.getResourceStream("org/columba/mail/action/searchtree_contextmenu.xml");

			menu = new MenuXMLDecoder(frameController).createPopupMenu(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Returns the pop up menu for the controller.
	 *
	 * @return the pop up menu.
	 */
	public JPopupMenu getPopupMenu() {
		return menu;
	}

	/**
	 * @see org.columba.mail.gui.tree.ITreeController#getSelected()
	 */
	public IMailFolder getSelected() {
		return selectedFolder;
	}

	/**
	 * Returns the mailFrameController.
	 *
	 * @return MailFrameController
	 */
	public IFrameMediator getFrameController() {
		return frameController;
	}

	/**
	 * ****************** TreeWillExpand Interface
	 * ******************************
	 */

	/** {@inheritDoc} */
	public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException {
		ResultTreeNode treeNode = (ResultTreeNode) e.getPath().getLastPathComponent();

		if (treeNode == null) {
			return;
		}
	}

	/** {@inheritDoc} */
	public void treeWillCollapse(TreeExpansionEvent e) {
		ResultTreeNode treeNode = (ResultTreeNode) e.getPath().getLastPathComponent();

		if (treeNode == null) {
			return;
		}
	}


	/**
	 * @see org.columba.mail.gui.tree.ITreeController#getModel()
	 */
	public TreeModel getModel() {
		return getView().getModel();
	}
	
	public void setModel(ResultTreeModel model)
	{
		getView().setModel(model);
	}

	/**
	 * @see org.columba.mail.gui.tree.ITreeController#setSortingEnabled(boolean)
	 */
	public void setSortingEnabled(boolean enabled) {
		//view.setSortingEnabled(enabled);
	}

	public void setSortingMode(SORTING_MODE_ENUM sortingMode, boolean ascending) {

		if (sortingMode == SORTING_MODE_ENUM.ALPHABETICAL) {
			setFolderComparator(new FolderComparator(ascending));
		} else if (sortingMode == SORTING_MODE_ENUM.UNREAD_COUNT) {
			setFolderComparator(new UnreadFolderComparator(ascending));
		} else {
			// no sorting
		}
	}

	/**
	 * Set a new folder comparator for sorting the folders.
	 *
	 * @param comparator
	 *            the folder comparator to use.
	 */
	private void setFolderComparator(FolderComparator comparator) 
	{
		folderComparator = comparator;
		//view.setSortingComparator(folderComparator);
	}

	public void addFolderSelectionListener(IFolderSelectionListener l) {
		listenerList.add(IFolderSelectionListener.class, l);
	}

	public void removeFolderSelectionListener(IFolderSelectionListener l) {
		listenerList.remove(IFolderSelectionListener.class, l);
	}

	protected void fireFolderSelectionChangedEvent(IMailFolder folder) {

		IFolderSelectionEvent e = new FolderSelectionEvent(this, folder);
		// Guaranteed to return a non-null array
		Object[] listeners = listenerList.getListenerList();

		// Process the listeners last to first, notifying
		// those that are interested in this event
		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == IFolderSelectionListener.class) {
				((IFolderSelectionListener) listeners[i + 1])
						.selectionChanged(e);
			}
		}
	}
	
	public void turnOnVertex(IMailFolder folder)
	{
		if(folder==null)
			return;
		
		Vertex vertex = ((VirtualFolder)folder).getVertex();
		System.out.println(vertex.toString());
		ISocialNetController socialNetController = ((SocialNetViewOwner)frameController).getSocialNetController();
		socialNetController.getSocialNetWorkRender().addToSignSet(getVertexTree(folder));
		socialNetController.getView().repaint();
	}
	
	private Vertex[] getVertexTree(IMailFolder folder)
	{
		TreeNode[] nodes = folder.getPath();
		Vertex [] vertexs = new Vertex[nodes.length-1];
		for(int i=1; i<nodes.length; i++)
		{
			vertexs[i-1] = ((IMailFolder)nodes[i]).getVertex();
		}
		return vertexs;
	}

	public void valueChanged(TreeSelectionEvent e) 
	{
		
	}

	
	public void resultArrived(IResultEvent event) 
	{
		
		List<ISearchResult> result = event.getSearchResults();
		ResultTreeModel model = new ResultTreeModel(result, event.getProviderName());
		setModel(model);
		getView().repaint();
	}

	public void clearSearch(IResultEvent event) {

	}

	public void reset(IResultEvent event) 
	{
		
	}

	public void finished(IResultEvent event) {
	}
	
	public String getSearchCriteriaTechnicalName()
	{
		return criteriaTechnicalName;
	}

	public String getProviderTechnicalName()
	{
		return providerTechnicalName;
	}

}
